﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ScreenMonitor
{
    public partial class SmartImageViewer : Control
    {
        /// <summary>
        /// 表示鼠标按下时选择的项目
        /// </summary>
        enum SelectedItemEnum
        {
            /// <summary>
            /// 图片窗口上
            /// </summary>
            ViewImage,
            /// <summary>
            /// 浏览窗口上
            /// </summary>
            PreviewBox,
            /// <summary>
            /// 浏览图片上
            /// </summary>
            PreviewImage,
        }

        #region==========属性==========

        private SmartImageProviderBase ImageProviderV;
        /// <summary>
        /// 获取或设置用来提供图片的源
        /// </summary>
        [Description("获取或设置用来提供图片的源")]
        [Browsable(true)]
        [ReadOnly(false)]
        public SmartImageProviderBase ImageProvider
        {
            get { return ImageProviderV; }
            set
            {
                ImageProviderV = value;
                ImageProvider.Init(this);
                base.Invalidate();
            }
        }

        private Rectangle ViewRectV;
        /// <summary>
        /// 获取或设置当前显示图片的矩形区域
        /// </summary>
        [Description("获取或设置当前显示图片的矩形区域")]
        public Rectangle ViewRect
        {
            get { return ViewRectV; }
            set
            {
                ViewRectV = value;
                this.Invalidate();
            }
        }

        private int ZoomPersentV;
        /// <summary>
        /// 获取或设置当前显示图片的缩放百分比
        /// </summary>
        [Description("获取或设置当前显示图片的缩放百分比")]
        public int ZoomPersent
        {
            get { return ZoomPersentV; }
            set
            {
                if (value <= 0)
                    ZoomPersent = 1;
                else
                {
                    ZoomPersentV = value;
                    this.Invalidate();
                    if (!IsLastPaintSuccess)
                    {
                        ZoomPersentV = ZoomPersentBackup;
                    }
                }
            }
        }

        private Rectangle PreviewBoxShowRectV;
        /// <summary>
        /// 获取或设置浏览图片的矩形区域
        /// </summary>
        [Description("获取或设置浏览图片的矩形区域")]
        public Rectangle PreviewBoxShowRect
        {
            get { return PreviewBoxShowRectV; }
            set
            {
                PreviewBoxShowRectV = value;
                this.Invalidate();
            }
        }

        private Color PreviewBoxColorV;
        /// <summary>
        /// 获取或设置缩略图窗格的背景颜色
        /// </summary>
        [Description("获取或设置缩略图窗格的背景颜色")]
        public Color PreviewBoxColor
        {
            get { return PreviewBoxColorV; }
            set
            {
                PreviewBoxColorV = value;
                this.Invalidate();
            }
        }

        #endregion

        #region========私有变量========

        private Point MouseDownPos;
        private Point MouseDownItemPos;
        private bool IsLastPaintSuccess = true;
        private int ZoomPersentBackup;
        internal RectangleF PreViewImgPaintRect;
        internal Rectangle PreviewSelectRect;
        private SelectedItemEnum SelectedItem;
        private SizeF ImageLogicSize;

        #endregion

        #region========私有函数========

        /// <summary>
        /// 根据当前参数获取物理图像
        /// </summary>
        /// <returns>获取到的物理图像</returns>
        private void DrawImage(Graphics g)
        {
            IsLastPaintSuccess = false;
            RectangleF DestRect = new RectangleF();                                   //源图裁剪区域
            SizeF ImageDestSize = new SizeF();                                        //图片缩放大小
            SizeF ImagePhysicalSize = ImageProviderV.GetImagePhysicalSize();          //图片物理大小
            Rectangle DrawRect = new Rectangle();

            //计算图片逻辑大小
            ImageLogicSize.Height = ImagePhysicalSize.Height * ZoomPersent / 100;
            ImageLogicSize.Width = ImagePhysicalSize.Width * ZoomPersent / 100;

            //越界判定
            if (ViewRectV.X < 0) ViewRectV.X = 0;
            if (ViewRectV.Y < 0) ViewRectV.Y = 0;
            if (ViewRectV.X + ViewRect.Width > ImageLogicSize.Width) ViewRectV.X = (int)ImageLogicSize.Width - ViewRect.Width;
            if (ViewRectV.Y + ViewRect.Height > ImageLogicSize.Height) ViewRectV.Y = (int)ImageLogicSize.Height - ViewRect.Height;

            if (ImageLogicSize.Height <= ViewRect.Height)//逻辑高度小于视图高度
            {
                DestRect.Y = 0;
                DestRect.Height = ImagePhysicalSize.Height;
                ImageDestSize.Height = ImageLogicSize.Height;
                DrawRect.Y = (int)(ViewRect.Height - ImageLogicSize.Height) / 2;
                DrawRect.Height = (int)ImageLogicSize.Height;
            }
            else//逻辑高度大于视图高度
            {
                DestRect.Y = ViewRect.Y / ImageLogicSize.Height * ImagePhysicalSize.Height;
                DestRect.Height = ViewRect.Height / ImageLogicSize.Height * ImagePhysicalSize.Height;
                ImageDestSize.Height = DestRect.Height;
                DrawRect.Y = 0;
                DrawRect.Height = ViewRect.Height;
            }
            if (ImageLogicSize.Width <= ViewRect.Width)//逻辑宽度小于视图宽度
            {
                DestRect.X = 0;
                DestRect.Width = ImagePhysicalSize.Width;
                ImageDestSize.Width = ImageLogicSize.Width;
                DrawRect.X = (int)(ViewRect.Width - ImageLogicSize.Width) / 2;
                DrawRect.Width = (int)ImageLogicSize.Width;
            }
            else//逻辑宽度大于视图宽度
            {
                DestRect.X = ViewRect.X / ImageLogicSize.Width * ImagePhysicalSize.Width;
                DestRect.Width = ViewRect.Width / ImageLogicSize.Width * ImagePhysicalSize.Width;
                ImageDestSize.Width = DestRect.Width;
                DrawRect.X = 0;
                DrawRect.Width = ViewRect.Width;
            }
            if (DestRect.Height < 1)
                return;
            if (DestRect.Width < 1)
                return;
            if (ImageDestSize.Width < 1)
                return;
            if (ImageDestSize.Height < 1)
                return;
            Image img = ImageProvider.GetPartImage(DestRect, ImageDestSize);
            g.DrawImage(img, DrawRect);
            img.Dispose();

            //绘制缩略图窗格
            g.FillRectangle(new System.Drawing.SolidBrush(PreviewBoxColor), PreviewBoxShowRect);
            Image PreviewImg = ImageProvider.GetPreviewImage(PreviewBoxShowRect.Size);
            if (PreviewImg.Width < PreviewBoxShowRect.Width)
            {
                PreViewImgPaintRect.X = (PreviewBoxShowRect.Width - PreviewImg.Width) / 2 + PreviewBoxShowRect.X;
                PreViewImgPaintRect.Width = PreviewImg.Width;
            }
            else
            {
                PreViewImgPaintRect.X = PreviewBoxShowRect.X;
                PreViewImgPaintRect.Width = PreviewBoxShowRect.Width;
            }
            if (PreviewImg.Height < PreviewBoxShowRect.Height)
            {
                PreViewImgPaintRect.Y = (PreviewBoxShowRect.Height - PreviewImg.Height) / 2 + PreviewBoxShowRect.Y;
                PreViewImgPaintRect.Height = PreviewImg.Height;
            }
            else
            {
                PreViewImgPaintRect.Y = PreviewBoxShowRect.Y;
                PreViewImgPaintRect.Height = PreviewBoxShowRect.Height;
            }
            g.DrawImage(PreviewImg, PreViewImgPaintRect);
            PreviewImg.Dispose();
            PreviewSelectRect.X = (int)(ViewRect.X / ImageLogicSize.Width * PreViewImgPaintRect.Width + PreViewImgPaintRect.X);
            PreviewSelectRect.Y = (int)(ViewRect.Y / ImageLogicSize.Height * PreViewImgPaintRect.Height + PreViewImgPaintRect.Y);
            PreviewSelectRect.Height = (int)(ViewRect.Height / ImageLogicSize.Height * PreViewImgPaintRect.Height);
            PreviewSelectRect.Width = (int)(ViewRect.Width / ImageLogicSize.Width * PreViewImgPaintRect.Width);
            g.DrawRectangle(new Pen(Color.CadetBlue, 1), PreviewSelectRect);

            IsLastPaintSuccess = true;
            ZoomPersentBackup = ZoomPersentV;
        }

        #endregion

        #region========构造函数========

        public SmartImageViewer()
        {
            InitializeComponent();
            this.MouseWheel += SmartImageViewer_MouseWheel;
            DoubleBuffered = true;
        }



        #endregion

        #region========绘制函数========

        protected override void OnPaint(PaintEventArgs pe)
        {
            if (ImageProviderV == null)
                base.OnPaint(pe);
            else
                if (ImageProviderV.IsInited())
                {
                    DrawImage(pe.Graphics);
                }
        }

        #endregion

        #region========事件函数========

        private void SmartImageViewer_SizeChanged(object sender, EventArgs e)
        {
            Rectangle rect = this.ViewRect;
            rect.Size = this.Size;
            this.ViewRect = rect;
        }

        private void SmartImageViewer_MouseDown(object sender, MouseEventArgs e)
        {
            MouseDownPos = e.Location;
            if (PreviewSelectRect.Contains(e.Location))
            {
                SelectedItem = SelectedItemEnum.PreviewImage;
                MouseDownItemPos = PreviewSelectRect.Location;
            }
            else if (PreviewBoxShowRect.Contains(e.Location))
            {
                SelectedItem = SelectedItemEnum.PreviewBox;
                MouseDownItemPos = PreviewBoxShowRect.Location;
            }
            else
            {
                SelectedItem = SelectedItemEnum.ViewImage;
                MouseDownItemPos = ViewRect.Location;
            }
        }

        private void SmartImageViewer_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                switch (SelectedItem)
                {
                    case SelectedItemEnum.ViewImage:
                        Rectangle viewrect = ViewRectV;
                        viewrect.X = MouseDownItemPos.X - e.X + MouseDownPos.X;
                        viewrect.Y = MouseDownItemPos.Y - e.Y + MouseDownPos.Y;
                        ViewRect = viewrect;
                        break;
                    case SelectedItemEnum.PreviewImage:
                        PreviewSelectRect.X = MouseDownItemPos.X + e.X - MouseDownPos.X;
                        PreviewSelectRect.Y = MouseDownItemPos.Y + e.Y - MouseDownPos.Y;
                        if (PreviewSelectRect.X < PreViewImgPaintRect.X)
                            PreviewSelectRect.X = (int)PreViewImgPaintRect.X;
                        if (PreviewSelectRect.X > PreViewImgPaintRect.Width - PreviewSelectRect.Width + PreViewImgPaintRect.X)
                            PreviewSelectRect.X = (int)(PreViewImgPaintRect.Width - PreviewSelectRect.Width + PreViewImgPaintRect.X);
                        if (PreviewSelectRect.Y < PreViewImgPaintRect.Y)
                            PreviewSelectRect.Y = (int)PreViewImgPaintRect.Y;
                        if (PreviewSelectRect.Y > PreViewImgPaintRect.Height - PreviewSelectRect.Height + PreViewImgPaintRect.Y)
                            PreviewSelectRect.Y = (int)(PreViewImgPaintRect.Height - PreviewSelectRect.Height + PreViewImgPaintRect.Y);
                        Rectangle viewrec = ViewRect;
                        viewrec.X = (int)((PreviewSelectRect.X - PreViewImgPaintRect.X) / PreViewImgPaintRect.Width * ImageLogicSize.Width);
                        viewrec.Y = (int)((PreviewSelectRect.Y - PreViewImgPaintRect.Y) / PreViewImgPaintRect.Height * ImageLogicSize.Height);
                        ViewRect = viewrec;
                        break;
                    case SelectedItemEnum.PreviewBox:
                        Rectangle previewboxrect = PreviewBoxShowRectV;
                        previewboxrect.X = MouseDownItemPos.X + e.X - MouseDownPos.X;
                        previewboxrect.Y = MouseDownItemPos.Y + e.Y - MouseDownPos.Y;
                        if (previewboxrect.X <= 0)
                            previewboxrect.X = 0;
                        if (previewboxrect.X > ViewRect.Width - previewboxrect.Width)
                            previewboxrect.X = ViewRect.Width - previewboxrect.Width;
                        if (previewboxrect.Y <= 0)
                            previewboxrect.Y = 0;
                        if (previewboxrect.Y > ViewRect.Height - previewboxrect.Height)
                            previewboxrect.Y = ViewRect.Height - previewboxrect.Height;
                        PreviewBoxShowRect = previewboxrect;
                        break;
                }




            }
        }

        void SmartImageViewer_MouseWheel(object sender, MouseEventArgs e)
        {
            ZoomPersent += e.Delta / 20;
        }

        #endregion

    }
}
